<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Value Holsters</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Value Holsters' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../intern.html">Inter Modules</a></li><li><a href="index.html">building</a></li><li><a href="index.html#3">Chapter 3: Masonry</a></li><li><b>Value Holsters</b></li></ul></div>
<p class="purpose">Representing compilation contexts, and holding compiled values.</p>

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. </b>Value holsters were created as a shim at a time when almost the entire Inform
code-base had to be turned around. Pre-2017, Inform generated code by writing
Inform 6 syntax out by hand: but post-2019, Inter bytecode was generated instead.
Hundreds of subsystems had to be rewritten, a process taking over a year, and
during this time the compiler had to work in a piebald sort of way &mdash; some
systems generating bytecode, others still pouring our raw I6 as text.
</p>

<p class="commentary">The <a href="3-vh.html#SP1" class="internal">value_holster</a> was invented as a way to manage this. It allows the caller
of a compilation function to ask for code to be made in a particular way: this
is the <span class="extract"><span class="extract-syntax">vhmode_wanted</span></span> field. These ways are:
</p>

<ul class="items"><li>&#9679; <span class="extract"><span class="extract-syntax">INTER_VAL_VHMODE</span></span> &mdash; generate Inter bytecode inside a function, producing a value
</li><li>&#9679; <span class="extract"><span class="extract-syntax">INTER_VOID_VHMODE</span></span> &mdash; generate Inter bytecode inside a function but in
void context, i.e., not producing a value
</li><li>&#9679; <span class="extract"><span class="extract-syntax">INTER_DATA_VHMODE</span></span> &mdash; encode a constant value as a pair of Inter values,
for use in, say, an array entry.
</li></ul>
<p class="commentary">So much for what the caller wants. The compilation function, or subsystem, then
does whatever it does, and sets <span class="extract"><span class="extract-syntax">vhmode_provided</span></span> to the mode it actually compiled
in; the caller can then deal with the situation arising if it wasn't what was
wanted. During 2017 this often meant that the function would write out some
raw I6 syntax, and reply <span class="extract"><span class="extract-syntax">INTER_TEXT_VHMODE</span></span> to signal this; the caller would
then turn this into Inter by wrapping it up as either a "splat" or a "glob".
</p>

<p class="commentary">With the transition now complete, <span class="extract"><span class="extract-syntax">INTER_TEXT_VHMODE</span></span> no longer exists. But
value holsters continue to be a useful device.
</p>

<pre class="definitions code-font"><span class="definition-keyword">enum</span> <span class="constant-syntax">INTER_DATA_VHMODE</span><span class="plain-syntax"> </span><span class="identifier-syntax">from</span><span class="plain-syntax"> </span><span class="constant-syntax">1</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">INTER_VAL_VHMODE</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">INTER_VOID_VHMODE</span>
<span class="definition-keyword">enum</span> <span class="constant-syntax">NO_VHMODE</span>
</pre>
<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">value_holster</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">vhmode_wanted</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">vhmode_provided</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">inter_pair</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">value_holster</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure value_holster is accessed in 2/eis and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">value_holster</span><span class="plain-syntax"> </span><span class="function-syntax">Holsters::new</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">Holsters::new</span></span>:<br/>Emitting Inter Schemas - <a href="2-eis.html#SP3_1_8">&#167;3.1.8</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">vhm</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">value_holster</span><span class="plain-syntax"> </span><span class="identifier-syntax">vh</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">vh</span><span class="plain-syntax">.</span><span class="element-syntax">val</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterValuePairs::undef</span><span class="plain-syntax">();</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">vh</span><span class="plain-syntax">.</span><span class="element-syntax">vhmode_wanted</span><span class="plain-syntax"> = </span><span class="identifier-syntax">vhm</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">vh</span><span class="plain-syntax">.</span><span class="element-syntax">vhmode_provided</span><span class="plain-syntax"> = </span><span class="constant-syntax">NO_VHMODE</span><span class="plain-syntax">; </span><span class="comment-syntax"> the compilation function has not yet set this</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">vhm</span><span class="plain-syntax"> == </span><span class="constant-syntax">NO_VHMODE</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"can't want NO_VHMODE"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">vh</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>A compilation function can produce, as its output, a value in either
<span class="extract"><span class="extract-syntax">INTER_DATA_VHMODE</span></span> (where this is exactly what is wanted) or in <span class="extract"><span class="extract-syntax">INTER_VAL_VHMODE</span></span>
(where it can easily be adapted).
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">Holsters::value_pair_allowed</span><span class="plain-syntax">(</span><span class="reserved-syntax">value_holster</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vh</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">vh</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no VH"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">vhmode_wanted</span><span class="plain-syntax"> == </span><span class="constant-syntax">INTER_DATA_VHMODE</span><span class="plain-syntax">) ||</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">vhmode_wanted</span><span class="plain-syntax"> == </span><span class="constant-syntax">INTER_VAL_VHMODE</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>This is how a compilation function "holsters" a value pair:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Holsters::holster_pair</span><span class="plain-syntax">(</span><span class="reserved-syntax">value_holster</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vh</span><span class="plain-syntax">, </span><span class="identifier-syntax">inter_pair</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">vh</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no VH"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">val</span><span class="plain-syntax"> = </span><span class="identifier-syntax">val</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">vhmode_provided</span><span class="plain-syntax"> = </span><span class="constant-syntax">INTER_DATA_VHMODE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>And this is how the caller "unholsters" that value, after the function has
returned. If we find <span class="extract"><span class="extract-syntax">NO_VHMODE</span></span>, we convert that to <span class="extract"><span class="extract-syntax">INTER_DATA_VHMODE</span></span> with
the literal number value 0.
</p>

<p class="commentary">On exit, the provided mode is always <span class="extract"><span class="extract-syntax">INTER_DATA_VHMODE</span></span>.
</p>

<p class="commentary">A second or subsequent call on the same holster does nothing, except to return
the same value pair, which is still stored in it. (In that sense, these aren't
really like a gunslinger's holster, where a revolver once drawn is no longer
in the holster.)
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">inter_pair</span><span class="plain-syntax"> </span><span class="function-syntax">Holsters::unholster_to_pair</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">Holsters::unholster_to_pair</span></span>:<br/><a href="3-vh.html#SP6">&#167;6</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">value_holster</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vh</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">vh</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no VH"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">vhmode_provided</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INTER_DATA_VHMODE:</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INTER_VAL_VHMODE:</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"impossible to unholster pair for compiled val code"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INTER_VOID_VHMODE:</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"impossible to unholster pair for compiled void code"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">NO_VHMODE:</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">vhmode_provided</span><span class="plain-syntax"> = </span><span class="constant-syntax">INTER_DATA_VHMODE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">val</span><span class="plain-syntax"> = </span><span class="identifier-syntax">InterValuePairs::number</span><span class="plain-syntax">(0);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">val</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b>If, on the other hand, the caller was asking for <span class="extract"><span class="extract-syntax">INTER_VAL_VHMODE</span></span>, it
should make use of the following. If we find <span class="extract"><span class="extract-syntax">NO_VHMODE</span></span>, we compile a <span class="extract"><span class="extract-syntax">val</span></span>
producing the literal value 0; if we find <span class="extract"><span class="extract-syntax">INTER_DATA_VHMODE</span></span>, we compile a
<span class="extract"><span class="extract-syntax">val</span></span> producing whatever value was holstered.
</p>

<p class="commentary">On exit, the provided mode is always <span class="extract"><span class="extract-syntax">INTER_VAL_VHMODE</span></span>.
</p>

<p class="commentary">A second or subsequent call on the same holster does nothing.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">Holsters::unholster_to_code_val</span><span class="plain-syntax">(</span><span class="identifier-syntax">inter_tree</span><span class="plain-syntax"> *</span><span class="identifier-syntax">I</span><span class="plain-syntax">, </span><span class="reserved-syntax">value_holster</span><span class="plain-syntax"> *</span><span class="identifier-syntax">vh</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">vh</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"no VH"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">switch</span><span class="plain-syntax"> (</span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">vhmode_provided</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INTER_DATA_VHMODE:</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">NO_VHMODE:</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">inter_pair</span><span class="plain-syntax"> </span><span class="identifier-syntax">val</span><span class="plain-syntax"> = </span><a href="3-vh.html#SP5" class="function-link"><span class="function-syntax">Holsters::unholster_to_pair</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">vh</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><a href="3-prd.html#SP32" class="function-link"><span class="function-syntax">Produce::val</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">I</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">val</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">vh</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">vhmode_provided</span><span class="plain-syntax"> = </span><span class="constant-syntax">INTER_VAL_VHMODE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INTER_VAL_VHMODE:</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">INTER_VOID_VHMODE:</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"impossible to use void Inter code in val context"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">            </span><span class="reserved-syntax">break</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="3-prd.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-bm.html">1</a></li><li class="progresschapter"><a href="2-is.html">2</a></li><li class="progresscurrentchapter">3</li><li class="progresssection"><a href="3-prd.html">prd</a></li><li class="progresscurrent">vh</li><li class="progressnextoff">&#10095;</li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

